package com.zdw.demo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zdw.demo.dto.TestDto;
import com.zdw.demo.entity.TestEntity;
import com.zdw.demo.mapper.TestDynamicMapper;
import com.zdw.demo.service.CustomerService;
import com.zdw.demo.service.TestDynamicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * <p>
 * 测试多数据源 服务实现类
 * </p>
 *
 * @author 卓德文
 * @since 2023-04-05
 */
@Service
@SuppressWarnings("all")
public class TestDynamicServiceImpl extends ServiceImpl<TestDynamicMapper, TestEntity> implements TestDynamicService {

    @Resource
    private CustomerService customerService;

    /**
     * 新增
     *
     * @param testDto
     * @return
     */
    @Override
    @DS("slave")
    public int save(TestDto testDto) {
        TestEntity testEntity = BeanUtil.copyProperties(testDto, TestEntity.class);
        return baseMapper.insert(testEntity);
    }

    /**
     * 修改
     *
     * @param testDto
     * @return
     */
    @Override
    @DS("slave")
    public int update(TestDto testDto) {
        TestEntity testEntity = BeanUtil.copyProperties(testDto, TestEntity.class);
        return baseMapper.update(testEntity, new UpdateWrapper<>());
    }

    /**
     * 测试多数据源、多数据源的事务问题
     *
     * @DS+@DSTransactional 会起一个本地线程的事务xid, 能控制方法内当前线程的所有事务
     * 注意不能和seata(事务失效)、@Transactional(事务错误/混乱)一起使用
     */
    @Override
    @DS("slave")
    @DSTransactional
    public boolean testDynamic(TestDto testDto) {
        //1.数据库B
        boolean b = this.save(testDto) > 1;

        /**
         * 2.切到数据库A
         * (注意:不能和seata一起用,spring.datasource.dynamic.seata必须为false,否则事务会失效)
         */
        int num = customerService.delete(testDto.getId());

        /**
         * 3.模拟报错,测试多数据源的事务问题
         *
         *  [1]@DSTransactional解决了切换数据源后方法B会报错(找不到表)的问题,否则方法B必须新开事务(这样会有问题,不推荐);
         *  [2]@DSTransactional不能和@Transactional一起使用,会造成事务问题,前者属于mp,后者属于spring;
         *  [3]@DSTransactional不能和seata一起用,即spring.datasource.dynamic.seata必须为false,否则事务会失效;   --重要
         */
        int i = 1 / 0;

        //4.返回
        return b;
    }

}
